<?php

namespace app\api\controller;

use app\common\controller\Api;

use AlibabaCloud\Client\AlibabaCloud;
use AlibabaCloud\Client\Exception\ClientException;
use AlibabaCloud\Client\Exception\ServerException;
use AlibabaCloud\Ecs\Ecs;
use app\common\model\Config;
use Overtrue\Pinyin\Pinyin;
use fast\Http;

/**
 * 首页接口
 */
class Index extends Api
{
    protected $noNeedLogin = ['*'];
    protected $noNeedRight = ['*'];

    /**
     * 首页
     *
     */
    public function index()
    {
        $this->success('请求成功');
    }

    public function getMulti()
    {
        $text = $this->request->param("text");
        $pinyin = new Pinyin(); // 默认
        $data = $pinyin->convert($text, PINYIN_UNICODE);
        return json_encode($data);
    }

    public function task()
    {
        $pinyin = new Pinyin(); // 格式化发言人的方法
        $post = $this->request->post();
        $requestUrl = "http://nls-gateway.cn-shanghai.aliyuncs.com/rest/v1/tts/async";
        $AccessKeyId = config('site.AccessKeyId');
        $AccessKeySecret = config('site.AccessKeySecret');
        $appkey = config('site.appkey');
        $text = $post['content'];
        $format = $post['format'];
        $voice = implode($pinyin->convert($post['voicer']));
        $speech_rate = $post['speed'] * 5;
        $pitch_rate = $post['pitch'] * 5;
        $notify_url = "http://".$_SERVER['HTTP_HOST'].config('site.return_url');

        /**
         * 处理传过来的数据并格式化为正确的SSML语句
         */

        $textArray = preg_split("/(?={语速-*[0-9]+})|({语速-*[0-9]+})|(?={语调-*[0-9]+})|({语调-*[0-9]+})|(?=\\n)|(\\n)|(?={@[a-zA-Z0-9\x{4e00}-\x{9fa5}]+})|({@[a-zA-Z0-9\x{4e00}-\x{9fa5}]+})/u",$text,-1,-1);
        $tempTextArray = array();
        for($i=0;$i<count($textArray);$i++){
            $temp = $textArray[$i][0];
            if(preg_match("/{语速-*[0-9]+}/",$temp)){
                continue;
            }else if(preg_match("/{语调-*[0-9]+}/",$temp)){
                continue;
            }else if(preg_match("/{@[a-zA-Z0-9\x{4e00}-\x{9fa5}]+}/u",$temp)){
                continue;
            }else if(preg_match("/\\n/",$temp)){
                if($post['wrap_stop']){
                    $tempTextArray[] = "<speak><break time=\"".$post['wrap_stop_sec']."\"ms /></speak>";
                }
            }else{
                $exitPitch = false;
                $exitRate = false;
                $exitVoice = false;
                $pitch = $pitch_rate;//语调
                $rate = $speech_rate;// 语速
                $tempVoice = $voice;
                for ($j=$i;$j>0&&!($exitPitch&&$exitRate&&$exitVoice);$j--){
                    if(preg_match("/{语调-*[0-9]+}/",$textArray[$j][0]) && !$exitPitch){
                        $pitch = intval(preg_replace("/{语调(-*[0-9]+)}/","$1",$textArray[$j][0])) * 5;
                        $exitPitch = true;
                    }
                    if(preg_match("/{语速-*[0-9]+}/",$textArray[$j][0]) && !$exitRate){
                        $rate = intval(preg_replace("/{语速(-*[0-9]+)}/","$1",$textArray[$j][0])) * 5;
                        $exitRate = true;
                    }
                    if(preg_match("/{@[a-zA-Z0-9\x{4e00}-\x{9fa5}]+}/u",$textArray[$j][0]) && !$exitVoice){
                        $tempVoice = implode($pinyin->convert(preg_replace("/{@[a-zA-Z0-9\x{4e00}-\x{9fa5}]+}}/u","$1",$textArray[$j][0])));
                        $exitVoice = true;
                    }
                }

                if(preg_match("/{[0-9]+秒}|{[0-9]+毫秒}/",$temp)){
                    $temp = preg_replace("/[{]([0-9]+)秒[}]/", "<break time=\"$1s\"/>", $temp);
                    $temp = preg_replace("/[{]([0-9]+)毫秒[}]/", "<break time=\"$1ms\"/>", $temp);
                    $tempTextArray[] = "<speak>".$temp."</speak>";
                }else if(preg_match("/{别名#([a-zA-Z0-9\x{4e00}-\x{9fa5}]+)=([a-zA-Z0-9\x{4e00}-\x{9fa5}]+)}/u",$temp)){
                    $temp = preg_replace("/\{别名#([a-zA-Z0-9\x{4e00}-\x{9fa5}]+)=([a-zA-Z0-9\x{4e00}-\x{9fa5}]+)}/u", "<sub alias=\"$2\">$1</sub>", $temp);
                    $tempTextArray[] = "<speak>".$temp."</speak>";
                }else if(preg_match("/\[pys\:([\x{4e00}-\x{9fa5}]+)\:([a-z]+[0-9])\]/u",$temp)){
                    $temp = preg_replace("/\[pys\:([\x{4e00}-\x{9fa5}]+)\:([a-z]+[0-9])\]/u",'<phoneme alphabet="py" ph="$2">$1</phoneme>',$temp);
                    $tempTextArray[] = "<speak>".$temp."</speak>";
                }
                $tempTextArray[] = "<speak pitch='".$pitch."' rate='".$rate."' voice='".$tempVoice."'>".$temp."</speak>";
            }
        }

        // 将转换完毕的数组重新组成字符串
        $text = implode("",$tempTextArray);

        // 判断用户余额是否足够
        $user = $this->auth->getUser();
        if($user->money < iconv_strlen(strip_tags($text))*config('site.price')){
            $this->error("当前余额不足以完成此次操作",strip_tags($text));
        }

        try {
            AlibabaCloud::accessKeyClient($AccessKeyId, $AccessKeySecret)->regionId("cn-shanghai")->asDefaultClient();
            $response = AlibabaCloud::nlsCloudMeta()->v20180518()->createToken()->request();
            $token = $response["Token"];
            if ($token == NULL) $this->error("Token错误");

            $header = array("appkey" => $appkey, "token" => $token['Id']);
            $context = array("device_id" => "Dev".time());
            $tts_request = array("text" => $text, "format" => $format, "voice" => $voice, "sample_rate" => 16000, "speech_rate"=>$speech_rate, "pitch_rate"=>$pitch_rate, "enable_subtitle" => false);
            $payload = array("enable_notify" => true, "notify_url" => $notify_url, "tts_request" => $tts_request);
            $tts_body = array("context" => $context, "header" => $header, "payload" => $payload);
            $body = json_encode($tts_body);
            $httpHeaders = array("Content-Type: application/json");

            $curl = curl_init();
            curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
            curl_setopt($curl, CURLOPT_URL, $requestUrl);
            curl_setopt($curl, CURLOPT_POST, TRUE);
            curl_setopt($curl, CURLOPT_HTTPHEADER, $httpHeaders);
            curl_setopt($curl, CURLOPT_POSTFIELDS, $body);
            curl_setopt($curl, CURLOPT_HEADER, TRUE);
            $response = curl_exec($curl);
            if ($response == FALSE) {
                curl_close($curl);
                $this->error("处理失败");
            }
            $headerSize = curl_getinfo($curl, CURLINFO_HEADER_SIZE);
            $headers = substr($response, 0, $headerSize);
            $bodyContent = substr($response, $headerSize);
            $http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
            if($http_code != 200) $this->error($bodyContent);
            curl_close($curl);
            $bodyContent = json_decode($bodyContent);
            if($bodyContent->error_code!='20000000') $this->error($bodyContent->error_message);
            // 数据处理成功，扣除金额并将记录写到数据库等待回调
            // $user = $this->auth->getUser();
            // $user->money = $user->money - iconv_strlen(strip_tags($text))*config('site.price');
            // $user->save();
            \app\common\model\User::money((0-iconv_strlen(strip_tags($text))*config('site.price')), $this->auth->id, "文字配音[".$bodyContent->request_id."]消耗");


            $model = new \app\common\model\exec\Lists();
            $model->order_no = $bodyContent->request_id;
            $model->name = $post['name'];
            $model->user_id = $this->auth->id;
            $model->voicer = $post['voicer'];
            $model->pay_money = iconv_strlen(strip_tags($text))*config('site.price');
            $model->status = 0;
            $model->save();
            $this->success("提交数据成功",$bodyContent);
        } catch (ClientException $e) {
            $this->error($e->getMessage());
        } catch (ServerException $exception) {
            // 获取错误消息
            $this->error($exception->getErrorMessage());
        }
    }

    public function notify(){
        $data = $this->request->param();
        $code = $data['error_code'];
        if($code == 20000000){
            $audio_address = $data['data']['audio_address'];
            $request_id = $data['request_id'];
            $model = new \app\common\model\exec\Lists();
            $list = $model->where("order_no",$request_id)->find();
            $list->status = 1;
            $list->down_url = htmlspecialchars_decode($audio_address);
            $list->save();
        }
    }

    public function tempTask(){
        $pinyin = new Pinyin(); // 格式化发言人的方法
        $post = $this->request->post();
        $requestUrl = "http://nls-gateway.cn-shanghai.aliyuncs.com/rest/v1/tts/async";
        $AccessKeyId = config('site.AccessKeyId');
        $AccessKeySecret = config('site.AccessKeySecret');
        $appkey = config('site.appkey');
        $text = $post['content'];
        $format = $post['format'];
        $voice = implode($pinyin->convert($post['voicer']));
        $speech_rate = $post['speed'] * 5;
        $pitch_rate = $post['pitch'] * 5;
        $notify_url = "http://".$_SERVER['HTTP_HOST'].config('site.return_url');



        $textArray = preg_split("/(?={语速-*[0-9]+})|({语速-*[0-9]+})|(?={语调-*[0-9]+})|({语调-*[0-9]+})|(?=\\n)|(\\n)|(?={@[a-zA-Z0-9\x{4e00}-\x{9fa5}]+})|({@[a-zA-Z0-9\x{4e00}-\x{9fa5}]+})/u",$text,-1,-1);
        $tempTextArray = array();
        for($i=0;$i<count($textArray);$i++){
            $temp = $textArray[$i][0];
            if(preg_match("/{语速-*[0-9]+}/",$temp)){
                continue;
            }else if(preg_match("/{语调-*[0-9]+}/",$temp)){
                continue;
            }else if(preg_match("/{@[a-zA-Z0-9\x{4e00}-\x{9fa5}]+}/u",$temp)){
                continue;
            }else if(preg_match("/\\n/",$temp)){
                if($post['wrap_stop']){
                    $tempTextArray[] = "<speak><break time=\"".$post['wrap_stop_sec']."\"ms /></speak>";
                }
            }else{
                $exitPitch = false;
                $exitRate = false;
                $exitVoice = false;
                $pitch = $pitch_rate;//语调
                $rate = $speech_rate;// 语速
                $tempVoice = $voice;
                for ($j=$i;$j>0&&!($exitPitch&&$exitRate&&$exitVoice);$j--){
                    if(preg_match("/{语调-*[0-9]+}/",$textArray[$j][0]) && !$exitPitch){
                        $pitch = intval(preg_replace("/{语调(-*[0-9]+)}/","$1",$textArray[$j][0])) * 5;
                        $exitPitch = true;
                    }
                    if(preg_match("/{语速-*[0-9]+}/",$textArray[$j][0]) && !$exitRate){
                        $rate = intval(preg_replace("/{语速(-*[0-9]+)}/","$1",$textArray[$j][0])) * 5;
                        $exitRate = true;
                    }
                    if(preg_match("/{@[a-zA-Z0-9\x{4e00}-\x{9fa5}]+}/u",$textArray[$j][0]) && !$exitVoice){
                        $tempVoice = implode($pinyin->convert(preg_replace("/{@[a-zA-Z0-9\x{4e00}-\x{9fa5}]+}}/u","$1",$textArray[$j][0])));
                        $exitVoice = true;
                    }
                }

                if(preg_match("/{[0-9]+秒}|{[0-9]+毫秒}/",$temp)){
                    $temp = preg_replace("/[{]([0-9]+)秒[}]/", "<break time=\"$1s\"/>", $temp);
                    $temp = preg_replace("/[{]([0-9]+)毫秒[}]/", "<break time=\"$1ms\"/>", $temp);
                }
                if(preg_match("/{别名#([a-zA-Z0-9\x{4e00}-\x{9fa5}]+)=([a-zA-Z0-9\x{4e00}-\x{9fa5}]+)}/u",$temp)){
                    $temp = preg_replace("/\{别名#([a-zA-Z0-9\x{4e00}-\x{9fa5}]+)=([a-zA-Z0-9\x{4e00}-\x{9fa5}]+)}/u", "<sub alias=\"$2\">$1</sub>", $temp);
                }
                if(preg_match("/\[pys:([\x{4e00}-\x{9fa5}]+):([a-z0-9]+)]/u",$temp)){
                    $temp = preg_replace("/\[pys:([\x{4e00}-\x{9fa5}]+):([a-z0-9]+)]/u",'<phoneme alphabet="py" ph="$2">$1</phoneme>',$temp);
                }
                $tempTextArray[] = "<speak pitch='".$pitch."' rate='".$rate."' voice='".$tempVoice."'>".$temp."</speak>";
            }
        }

        // 将转换完毕的数组重新组成字符串
        $text = implode("",$tempTextArray);

        try {
            AlibabaCloud::accessKeyClient($AccessKeyId, $AccessKeySecret)->regionId("cn-shanghai")->asDefaultClient();
            $response = AlibabaCloud::nlsCloudMeta()->v20180518()->createToken()->request();
            $token = $response["Token"];
            if ($token == NULL) $this->error("Token错误");

            $header = array("appkey" => $appkey, "token" => $token['Id']);
            $context = array("device_id" => "Dev".time());
            $tts_request = array("text" => $text, "format" => $format, "voice" => $voice, "sample_rate" => 16000, "speech_rate"=>$speech_rate, "pitch_rate"=>$pitch_rate, "enable_subtitle" => false);
            $payload = array("enable_notify" => true, "notify_url" => $notify_url, "tts_request" => $tts_request);
            $tts_body = array("context" => $context, "header" => $header, "payload" => $payload);
            $body = json_encode($tts_body);
            $httpHeaders = array("Content-Type: application/json");

            $curl = curl_init();
            curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
            curl_setopt($curl, CURLOPT_URL, $requestUrl);
            curl_setopt($curl, CURLOPT_POST, TRUE);
            curl_setopt($curl, CURLOPT_HTTPHEADER, $httpHeaders);
            curl_setopt($curl, CURLOPT_POSTFIELDS, $body);
            curl_setopt($curl, CURLOPT_HEADER, TRUE);
            $response = curl_exec($curl);
            if ($response == FALSE) {
                curl_close($curl);
                $this->error("处理失败");
            }
            $headerSize = curl_getinfo($curl, CURLINFO_HEADER_SIZE);
            $headers = substr($response, 0, $headerSize);
            $bodyContent = substr($response, $headerSize);
            $http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
            if($http_code != 200) $this->error($bodyContent);
            curl_close($curl);
            $bodyContent = json_decode($bodyContent);
            if($bodyContent->error_code!='20000000') $this->error($bodyContent->error_message);
            // 监听查询结果
            $fullUrl = $requestUrl . "?appkey=" . $appkey . "&task_id=" . $bodyContent->data->task_id . "&token=" . $token['Id'] . "&request_id=" . $bodyContent->request_id;
            while (true){
                $listenResult = Http::get($fullUrl);
                $listenResult = json_decode($listenResult);
                if($listenResult->status == 200 && $listenResult->error_code == "20000000"){
                    if($listenResult->error_message == "RUNNING" || $listenResult->error_message == "QUEUEING"){
                        sleep(1);
                    }else if($listenResult->error_message == "SUCCESS"){
                        $this->success("成功", $listenResult->data->audio_address);
                    }else {
                        $this->error($listenResult->error_message);
                    }
                }else{
                    $this->error("试听错误");
                }
            }
        } catch (ClientException $e) {
            $this->error($e->getMessage());
        } catch (ServerException $exception) {
            // 获取错误消息
            $this->error($exception->getErrorMessage());
        }
    }
}
